package game.breeze.screen;

import game.breeze.Breeze;
import game.breeze.ani.Animation;
import game.breeze.ani.ListAction;
import game.breeze.ani.Move;
import game.breeze.ani.OnActionProgress;
import game.breeze.ani.OnAnimationCompleted;
import game.breeze.assets.Assets;
import game.breeze.constants.MapItemType;
import game.breeze.data.c.GameMap;
import game.breeze.data.c.MapItem;
import game.breeze.data.c.Monster;
import game.breeze.data.c.Npc;
import game.breeze.message.AppMessage;
import game.breeze.message.SceneMessageCode;
import game.breeze.screen.actors.MotionActor;
import game.breeze.screen.actors.listener.IMotionListener;
import game.breeze.screen.group.SpriteGroup;
import game.breeze.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.OnActionCompleted;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.FadeIn;
import com.badlogic.gdx.scenes.scene2d.actions.FadeOut;
import com.badlogic.gdx.scenes.scene2d.actions.MoveBy;
import com.badlogic.gdx.scenes.scene2d.actions.Parallel;
import com.badlogic.gdx.scenes.scene2d.actions.RotateTo;
import com.badlogic.gdx.scenes.scene2d.actions.ScaleTo;
import com.badlogic.gdx.scenes.scene2d.actions.Sequence;
import com.badlogic.gdx.scenes.scene2d.actors.Image;
import com.badlogic.gdx.scenes.scene2d.actors.Label;

public class GameScreen extends BreezeScreen implements IMotionListener {
	private GameMap map;
	private Group buildGroup;
	private SpriteGroup spriteGroup;
	public SpriteGroup motionGroup;
	public MotionActor player;
	private Image backgroud;
	private Group root;
	// 已获取的场景物品
	private List<String> pickedItems = new ArrayList<String>();
	// 场景中的怪物
	private Map<Integer, MotionActor> monsters;
	// 點擊位置
	private Vector2 prePosition = new Vector2();
	// 當前坐標
	private Vector2 backPosition = new Vector2();
	// 提示文本
	private Label tips;
	// 提示消息列表
	private LinkedList<String> tipMessages = new LinkedList<String>();
	// 可移动范围
	int wr = 0;
	// 可移动范围
	int hr = 0;

	public void onMonsterStatus(List<Monster> ms) {
		try {
			lock.lock();
			if (monsters == null) {
				return;
			}
			Monster m = null;
			for (int i = 0; i < ms.size(); i++) {
				m = ms.get(i);
				// 改变状态
				if (monsters.containsKey(m.getId())) {
					// 移除舞台
					if (m.isDead()) {
						monsters.remove(m.getId()).remove();
					} else {
						monsters.get(m.getId()).setPosition(m.getX(), m.getY());
					}
				} else {// 添加至舞台.
					MotionActor ma = new MotionActor("" + m.getId(), Assets.moveAni, Assets.moveAni, map.getCellSize());
					ma.setPosition(m.getX(), m.getY());
					monsters.put(m.getId(), ma);
					spriteGroup.addActor(ma);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	@Override
	public void onPositionChange(MotionActor sprite, Vector2 position) {
		AppMessage msg = AppMessage.createMessage(AppMessage.MSG_SCENE);
		msg.getBuffer().writeInt(SceneMessageCode.MSG_SCENE_PLAYER_MOVE);
		msg.getBuffer().writeInt(map.getId());
		msg.getBuffer().writeInt((int) position.x);
		msg.getBuffer().writeInt((int) position.y);
		// game.socket.sendMessage(msg);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * game.breeze.screen.actors.listener.IMotionListener#onMotionStop(game.
	 * breeze.screen.actors.MotionActor, com.badlogic.gdx.math.Vector2)
	 */
	@Override
	public void onMotionStop(MotionActor sprite, Vector2 position) {

	}

	public void hitProcess(int hitID, Vector2 position) {
		if (hitID <= 0) {
			return;
		}
		final MapItem mi = map.items.get(hitID);
		// 如果不在右边
		float deltaX = position.x - mi.getX() - mi.getWidth();
		float deltaY = Math.abs(position.y - mi.getY());
		if (!(deltaX >= -map.getCellSize() && deltaX <= map.getCellSize() * 2 && deltaY <= map.getCellSize())) {
			// return;
		}

		if (mi.getId() == 20003) {// 毛铁
			// 毛铁消失.
			buildGroup.findActor("" + mi.getId()).remove();
			// 获取道具
			pickedItems.add("" + mi.getId());
		} else if (mi.getId() == 20004) {// 树
			// 需要毛铁.如果有毛铁,播放砍树动画,
			if (pickedItems.contains(20003)) {// 没有道具
				addTipMessage("need item");
			} else {// 有,消耗道具
				// 动画位置
				float motionX = mi.getX() + mi.getWidth() * .6f;
				float motionY = mi.getY();
				// 人物在下面
				root.swapActor(buildGroup, spriteGroup);
				// 移除道具
				pickedItems.remove("" + 20003);
				// 攻击
				player.playMotion(Assets.cutAni, new OnAnimationCompleted() {
					@Override
					public void onCompleted() {
						// 人物回复原位
						root.swapActor(buildGroup, spriteGroup);
						// 移除原树
						buildGroup.findActor("" + mi.getId()).remove();
						// 播放树倒
						Image treeFall = new Image("c_20002", Assets.treeFall.getKeyFrame(0));
						treeFall.x = 758;
						treeFall.y = 618;

						// 播放树倒
						treeFall.action(ListAction.$(Assets.treeFall, 0, Animation.ANIMATION_NONLOOPING).setCompletionListener(new OnActionCompleted() {
							@Override
							public void completed(Action action) {
								// 移除动画,添加树桩
								action.getTarget().remove();
								// 树桩
								Image treeTail = new Image("c_20002", map.items.get(20002).getRegion());
								treeTail.x = 931;
								treeTail.y = 685;
								buildGroup.addActor(treeTail);

								treeTail = new Image("c_tree_in_river", Assets.treeInRiver);
								treeTail.x = 765;
								treeTail.y = 652;
								treeTail.action(Sequence.$(Parallel.$(ScaleTo.$(1.1f, 1.1f, 16), MoveBy.$(75, -80, 16)), Parallel.$(ScaleTo.$(1.2f, 1.2f, 24), MoveBy.$(-50, -120, 24)), Parallel.$(ScaleTo.$(1.3f, 1.3f, 16), MoveBy.$(50, -80, 16)),
										Parallel.$(ScaleTo.$(1.4f, 1.4f, 36), MoveBy.$(-90, -180, 36)), Parallel.$(ScaleTo.$(1.5f, 1.5f, 36), MoveBy.$(-3, -110, 20), RotateTo.$(-10, 20))));
								buildGroup.addActorAt(0, treeTail);
							}
						}));
						buildGroup.addActor(treeFall);
					}
				}, Animation.ANIMATION_LOOPING, motionX, motionY);
			}
		}
	}

	public GameScreen(Breeze game) {
		super(game);
		stage = new GameStage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
		// StartAssets.load();
		Assets.load();
		map = Assets.loadMap(10002);
		Gdx.input.setInputProcessor(stage);
	}

	// TIP是不是正在显示
	private boolean showing = false;

	@Override
	public void render(float delta) {
		try {
			lock.lock();
			showTips();
			// tips.x = -(backPosition.x - stage.centerX() + tips.width / 2);
			// tips.y = -(backPosition.y - stage.centerY() + tips.height / 2);
			spriteGroup.update(delta);
			motionGroup.update(delta);
			stage.act(delta);
			stage.draw();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void addTipMessage(String msg) {
		try {
			lock.lock();
			tipMessages.add(msg);
		} finally {
			lock.unlock();
		}
	}

	private void showTips() {
		// 如果没有正在显示的TIPS,并有需要显示的TIPS
		if (!showing && tipMessages.size() > 0) {
			// 正在显示
			showing = true;
			// TIPS文本
			tips.setText(tipMessages.pollFirst());
			// 坐标
			tips.x = -(backPosition.x - stage.centerX() + tips.width / 2);
			// 坐标
			tips.y = -(backPosition.y - stage.centerY() + tips.height / 2);
			// 隐藏
			tips.color.a = 0;
			// 动画
			tips.action(Sequence.$(FadeIn.$(2), FadeOut.$(2)).setCompletionListener(new OnActionCompleted() {
				@Override
				public void completed(Action action) {
					// 动画结束移除
					action.getTarget().remove();
					// TIPS显示完成
					showing = false;
				}
			}));
			// 添加TIPS
			stage.addActor(tips);
		}
	}

	@Override
	public void show() {
		backgroud = new Image("backgroud", map.getRegion());
		wr = map.getRegion().getRegionWidth() - Gdx.graphics.getWidth();
		hr = map.getRegion().getRegionHeight() - Gdx.graphics.getHeight();
		spriteGroup = new SpriteGroup();
		buildGroup = new SpriteGroup();
		motionGroup = new SpriteGroup();
		root = new Group("scene");
		tips = new Label("tips", Assets.font);

		monsters = Collections.synchronizedMap(new HashMap<Integer, MotionActor>());

		for (MapItem item : map.items.values()) {
			if (item.getMapItemType() == MapItemType.npc) {
				MotionActor npc = new MotionActor("" + item.getId(), ((Npc) item).getAni(), ((Npc) item).getAni(), 32);
				npc.setPosition(item.getX(), item.getY());
				motionGroup.addActor(npc);
			} else if (item.getMapItemType() == MapItemType.build) {
				Image img = new Image("" + item.getId(), item.getRegion());
				img.x = item.getX();
				img.y = item.getY();
				img.rotation = item.getRotate();
				buildGroup.addActor(img);
			}
		}

		player = new MotionActor("sprite_", Assets.moveAni, Assets.standAni, map.getCellSize());
		player.setPosition(992, 736);
		player.setListener(this);
		spriteGroup.addActor(player);

		root.addActor(backgroud);
		root.addActor(buildGroup);
		root.addActor(motionGroup);
		root.addActor(spriteGroup);

		root.x = -wr;
		root.y = -hr;

		stage.addActor(root);
	}

	@Override
	public void dispose() {
		super.dispose();
		spriteGroup.clear();
		buildGroup.clear();
		motionGroup.clear();
		map = null;
		spriteGroup = null;
		buildGroup = null;
		player = null;
		motionGroup = null;
	}

	class GameStage extends Stage {
		private boolean needPath;

		public GameStage(float width, float height, boolean stretch) {
			super(width, height, stretch);
		}

		@Override
		public boolean touchDown(int x, int y, int pointer, int button) {
			needPath = true;
			toStageCoordinates(x, y, prePosition);
			int clickX = (int) (wr - root.x + prePosition.x);
			int clickY = (int) (hr - root.y + prePosition.y);
			Actor hitA = buildGroup.hit(clickX, clickY);
			// 有碰撞,说明不可达
			if (hitA != null) {
				// 不寻路
				needPath = false;
				// 碰撞处理
				hitProcess(StringUtils.toInteger(hitA.name), player.getPostion());
			}

			Gdx.input.setOnscreenKeyboardVisible(true);

			return super.touchDown(x, y, pointer, button);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see com.badlogic.gdx.scenes.scene2d.Stage#touchUp(int, int, int,
		 * int)
		 */
		@Override
		public boolean touchUp(int x, int y, int pointer, int button) {
			if (needPath) {
				toStageCoordinates(x, y, prePosition);
				Vector2 originPosition = player.getPostion();
				int clickX = (int) (wr - root.x + prePosition.x);
				int clickY = (int) (hr - root.y + prePosition.y);

				if ((clickX / map.getCellSize() != originPosition.x / map.getCellSize()) && (clickY / map.getCellSize() != originPosition.y / map.getCellSize())) {
					AppMessage msg = AppMessage.createMessage(AppMessage.MSG_SCENE);
					msg.getBuffer().writeInt(SceneMessageCode.MSG_SCENE_PLAYER_FIND_PATH);
					msg.getBuffer().writeInt(map.getId());
					msg.getBuffer().writeInt((int) originPosition.x);
					msg.getBuffer().writeInt((int) originPosition.y);
					msg.getBuffer().writeInt(clickX);
					msg.getBuffer().writeInt(clickY);
					// game.socket.sendMessage(msg);
				}
			}

			// 在显示TIPS的时候不能滑动.
			if (!showing) {
				Vector2 now = new Vector2();
				toStageCoordinates(x, y, now);

				backPosition.x += (now.x - prePosition.x);
				backPosition.y += (now.y - prePosition.y);

				backPosition.x = (backPosition.x <= 0) ? 0 : backPosition.x;
				backPosition.x = (backPosition.x >= wr) ? wr : backPosition.x;

				backPosition.y = (backPosition.y <= 0) ? 0 : backPosition.y;
				backPosition.y = (backPosition.y >= hr) ? hr : backPosition.y;

				root.action(Move.$(backPosition.x, backPosition.y, 2).setProgressListener(new OnActionProgress() {
					@Override
					public void progress(Action action) {
						backPosition.x = action.getTarget().x;
						backPosition.y = action.getTarget().y;
					}
				}));
			}

			return super.touchUp(x, y, pointer, button);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see com.badlogic.gdx.scenes.scene2d.Stage#touchDragged(int, int,
		 * int)
		 */
		@Override
		public boolean touchDragged(int x, int y, int pointer) {
			needPath = false;

			return super.touchDragged(x, y, pointer);
		}
	}
}
